#include "H264Source.h"
#include <chrono>

namespace jlh
{
	H264Source* H264Source::CreateNew(uint32_t framerate)
	{
		return new H264Source(framerate);
	}
	H264Source::H264Source(uint32_t framerate)
		: framerate_(framerate)
	{
		payload_ = 96;
		media_type_ = H264;
		clock_rate_ = 90000;
	}

	H264Source::~H264Source()
	{

	}

	std::string H264Source::GetMediaDescription(uint16_t port)
	{
		char buf[128] = { 0 };
		sprintf_s(buf, 128, "m=video %hu RTP/AVP 96", port);
		return std::string(buf);
	}
	std::string H264Source::GetAttribute()
	{
		return std::string("a=rtpmap:96 H264/90000");
	}
	bool H264Source::HandleFrame(MediaChannelId channelId, AVFrame frame)
	{
		uint8_t* frame_buf = frame.buffer.get();
		uint32_t frame_size = frame.size;

		//timestamp == 0
		if (frame.timestamp == 0)
		{
			frame.timestamp = H264Source::GetTimestamp();
			//printf("F%u ", frame.timestamp);
		}

		if (frame_size <= MAX_RTP_PAYLOAD_SIZE)
		{
			RtpPacket rtp_pkt;
			rtp_pkt.type = frame.type;
			rtp_pkt.timestamp = frame.timestamp;
			rtp_pkt.size = frame_size + 4 + RTP_HEADER_SIZE;
			rtp_pkt.last = 1;
			memcpy(rtp_pkt.data.get() + 4 + RTP_HEADER_SIZE, frame_buf, frame_size);
			if (send_frame_callback_)
			{
				if (!send_frame_callback_(channelId, rtp_pkt))
					return false;
			}
		}
		else
		{
			char FU_A[2] = { 0 };
			FU_A[0] = (frame_buf[0] & 0xE0) | 28;
			FU_A[1] = 0x80 | (frame_buf[0] & 0x1F);

			frame_buf += 1;
			frame_size -= 1;

			while (MAX_RTP_PAYLOAD_SIZE < 2 + frame_size)
			{
				RtpPacket rtp_pkt;
				rtp_pkt.type = frame.type;
				rtp_pkt.timestamp = frame.timestamp;
				rtp_pkt.size = 4 + RTP_HEADER_SIZE + MAX_RTP_PAYLOAD_SIZE;
				rtp_pkt.last = 0;
				rtp_pkt.data.get()[RTP_HEADER_SIZE + 4] = FU_A[0];
				rtp_pkt.data.get()[RTP_HEADER_SIZE + 5] = FU_A[1];
				memcpy(rtp_pkt.data.get() + 4 + RTP_HEADER_SIZE + 2, frame_buf, MAX_RTP_PAYLOAD_SIZE - 2);

				if (send_frame_callback_)
				{
					if (!send_frame_callback_(channelId, rtp_pkt))
						return false;
				}

				frame_buf += MAX_RTP_PAYLOAD_SIZE - 2;
				frame_size -= MAX_RTP_PAYLOAD_SIZE - 2;
				FU_A[1] &= ~0x80;
			}

			{
				RtpPacket rtp_pkt;
				rtp_pkt.type = frame.type;
				rtp_pkt.timestamp = frame.timestamp;
				rtp_pkt.size = 4 + RTP_HEADER_SIZE + 2 + frame_size;
				rtp_pkt.last = 1;
				FU_A[1] |= 0x40;
				rtp_pkt.data.get()[RTP_HEADER_SIZE + 4] = FU_A[0];
				rtp_pkt.data.get()[RTP_HEADER_SIZE + 5] = FU_A[1];
				memcpy(rtp_pkt.data.get() + 4 + RTP_HEADER_SIZE + 2, frame_buf, frame_size);
				if (send_frame_callback_)
				{
					if (!send_frame_callback_(channelId, rtp_pkt))
						return false;
				}
			}
		}

		return true;
	}

    //把微妙单位的系统时钟转换为90kHz的视频时间戳
    //1. System.ticks * (1/10^6) = Rtp.ts*(1/90*10^3)
    //2. Rtp.ts = System.ticks/10^6 * 90*10^3
    //3. Rtp.ts = System.ticks/1000 * 90
	uint32_t H264Source::GetTimestamp()
	{//当前系统时钟,now()为单调递增,不受系统时间影响,即使系统时间被篡改
		auto time_point = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::steady_clock::now());
		return (uint32_t)((time_point.time_since_epoch().count()+500) / 1000 * 90);
	}
}